In [29]:
import pandas as pd
import numpy as np
import plotly.graph_objects as go

# Para la realización de esta visualización se utilizará el set de datos EstadisticasAtaques2017_2020_Input_Visualization
# el cual tiene la distribución de ataques como variable categórica y no variable numérica.
url = 'https://raw.githubusercontent.com/iruiper/Cyberattacks-History/master/data/01_clean/EstadisticasAtaques2017_2020_Input_Visualization.csv'

# Columnas seleccionadas para realizar las visualizaciones
cols=['Continent', 'Author_processed', 'Code_attack_class', 'Desc_target_class']
df = pd.read_csv(url, sep=';', decimal=',', encoding='latin-1')

# Diccionario utilizado para ajustar las etiquetas en los gráficos
adjust_label = {
    'Public administration and defence, compulsory social security': 'Public administration<br>and defence, compulsory<br>social security',
    'Financial and insurance activities': 'Financial and<br>insurance activities',
    'Information and communication': 'Information and<br>communication',
    'Arts entertainment and recreation': 'Arts entertainment<br>and recreation',
    'Human health and social work activities': 'Human health and<br>social work activities',
    'Education': 'Education',
    'Fintech': 'Fintech',
    'Manufacturing': 'Manufacturing',
    'Transportation and storage': 'Transportation and<br>storage',
    'Professional scientific and technical activities': 'Professional scientific<br>and technical<br>activities',
    'Other services activities': 'Other services<br>activities'

}

# Diccionario utilizado para modificar las etiquetas en los gráficos
attack_label = {
    'H': 'Hactivism',
    'CE': 'Cyber<br>Espionage',
    'CC': 'Cyber<br>Crime',
    'CW': 'Cyber<br>Warfare'
}

# Descartamos aquellos ataques internacionales y desconocidos, así como aquellos sectores detectados como outliers
data = df.loc[~(df.Continent.isin(['International', 'Desconocido'])) & ~(df.Code_target_class.isin(['X', 'Y', 'Z']))]

# Se asigna a las observaciones del sector público un color diferente para facilitar la detección de elementos en el gráfico.
data.loc[:, 'Color'] = data.Desc_target_class.map(lambda x: 'rgba(14,76,112,0.9)' if x == 'Public administration and defence, compulsory social security' else 'rgba(130,201,241,0.4)')

# Modificación de las descripciones de los sectores a traves del diccionario adjust_label
data.loc[:, 'Desc_target_class'] = data.Desc_target_class.where(data.Desc_target_class.map(adjust_label).isnull(),
                                                                data.Desc_target_class.map(adjust_label))

# Modificación de las tipologias de ataque
data.loc[:, 'Code_attack_class'] = data.Code_attack_class.map(attack_label)


def create_sankey(df, title):
    """

    Función que permitirá crear un parallel set en función de los datos introducidos. Este parallel set contendrá
    información de los 5 sectores más atacados en cada continente.
    
    df: dataframe con los ataques filtrados por continente
    title: título del gráfico.

    """
    
    # Se agrupan los datos en función del sector atacado, contando el número de ataques recibidos en cada
    # sector con el objetivo de obtener el top 5 sectores.
    attack_df = df.groupby(['Desc_target_class'], as_index=False).count()
    attack_df.sort_values('Mes', ascending=False, inplace=True)
    
    # Filtramos el dataframe original quedándonos con aquellas observaciones que pertenezcan al top 5 de sectores 
    # atacados
    data = df[df.Desc_target_class.isin(attack_df.head(5).Desc_target_class)]

    # Creación de los distintos niveles del parallel set. El orden será Autor, Tipo de ataque y sector afetado
    Author_dim = go.parcats.Dimension(values=data.Author_processed, label='Autor del Ataque')
    Ataque_dim = go.parcats.Dimension(values=data.Code_attack_class, label='Tipo Ataque')
    Target_dim = go.parcats.Dimension(values=data.Desc_target_class, label='Sector Afectado')

    # Creación del gráfico
    figg = go.Figure(data=[go.Parcats(dimensions=[Author_dim, Ataque_dim, Target_dim],
                                      line={'color': data.Color})])
    # Estética del gráfico.
    figg.update_layout(
        title={'text':title, 'x':0.5, 'xanchor':'center', 'yanchor': 'top'},
        titlefont=dict(size=18),
        height=500,
        width=800,
        showlegend=False
    )

    figg.show('notebook')
In [30]:
# Creación del parllel set para Europa
create_sankey(data[data.Continent == 'Europa'], title='Top 5 Sectores receptores<br> de Ciberataques en Europa')
In [31]:
# Creación del parllel set para Africa
create_sankey(data[data.Continent == 'África'], title='Top 5 Sectores receptores<br> de Ciberataques en África')
In [32]:
# Creación del parllel set para America
create_sankey(data[data.Continent == 'América'], title='Top 5 Sectores receptores<br> de Ciberataques en América')
In [33]:
# Creación del parllel set para Asia
create_sankey(data[data.Continent == 'Asia'], title='Top 5 Sectores receptores<br> de Ciberataques en Asia')
In [34]:
# Creación del parllel set para Australia y Oceanía
create_sankey(data[data.Continent == 'Australia y Oceanía'], title='Top 5 Sectores receptores<br> de Ciberataques en Australia y Oceanía')
In [ ]: